package com.kernowsoft.wavefx;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Locale;

import com.kernowsoft.wavefx.R;
import com.kernowsoft.wavefx.specdraw.SpecData;
import com.kernowsoft.wavefx.specdraw.SpecDraw;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class SpecDrawActivity extends Activity {

	private static final String TAG = "SpecDrawActivity";

	private SpecDraw mSpecDraw;
	private SpecData mSpecData;
	private ProgressBar mProgressBar;
	private CheckBox mLogScaleCheckBox;
	private SeekBar mMaxFreqSlider;

	private ProgressDialog mProgressDialog;

	// private Vector<SpecData> mSpecDataList;
	private HashMap<String, SpecData> mSpecDataCache;
	private String mStrSite = null;
	private int mFcHr = 0;

	private static final int SELECT_SITE_ID = Menu.FIRST;
	private static final int HELP_ID = Menu.FIRST + 1;

	@SuppressLint("NewApi")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_spec_draw);
		
	    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // Show the Up button in the action bar.
            getActionBar().setDisplayHomeAsUpEnabled(true);
        }

		mSpecDraw = (SpecDraw) findViewById(R.id.specDraw);
		mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
		mLogScaleCheckBox = (CheckBox) findViewById(R.id.logScaleCheckBox);
		mMaxFreqSlider = (SeekBar) findViewById(R.id.sliderFreqRange);

		// specData = new SpecData(); // for storing spec data

		// create progress dialog
		mProgressDialog = new ProgressDialog(this);
		mProgressDialog.setMessage("Loading data");
		mProgressDialog.setIndeterminate(false);
		mProgressDialog.setMax(100);
		mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		

		// initial values
		mLogScaleCheckBox.setChecked(mSpecDraw.isLogScale());
		mMaxFreqSlider.setMax(100);
		mMaxFreqSlider.setProgress(100);
		mProgressBar.setVisibility(View.INVISIBLE);

		mSpecDataCache = new HashMap<String, SpecData>();

		/*
		 * Set up listeners:
		 */

		// listener for log scale check box change:
		mLogScaleCheckBox
				.setOnCheckedChangeListener(new OnCheckedChangeListener() {
					@Override
					public void onCheckedChanged(CompoundButton buttonView,
							boolean isChecked) {
						mSpecDraw.setLogScale(isChecked);
					}

				});

		// set listener for image view taps:
		mSpecDraw.setOnTouchListener(new View.OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {

				// catch only location when action up:
				switch (event.getAction()) {
				case MotionEvent.ACTION_UP:
					Log.d(TAG,
							"Up:  X/Y: " + event.getRawX() + ","
									+ event.getRawY());
					return false;

				case MotionEvent.ACTION_DOWN:

					float l = v.getLeft();
					float r = v.getRight();
					float mid = l + ((r - l) / 2.0f);
					float x = event.getRawX();
					Log.d(TAG,
							"Down: L/R, X/Y:" + l + "," + r + "   "
									+ event.getRawX() + "," + event.getRawY());

					if (x < mid)
						mFcHr -= 3;
					else if (x > mid)
						mFcHr += 3;

					if (mFcHr > 144)
						mFcHr = 0;
					if (mFcHr < 0)
						mFcHr = 144;

					// load the image:
					loadData();

					return true;
				}
				return false;
			}
		});

		mMaxFreqSlider
				.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

					@Override
					public void onStopTrackingTouch(SeekBar seekBar) {
						float maxFreq = 0.65f - 0.4f / 100 * (100 - seekBar
								.getProgress());
						mSpecDraw.setMaxFreq(maxFreq);
					}

					@Override
					public void onStartTrackingTouch(SeekBar seekBar) {
						// TODO Auto-generated method stub

					}

					@Override
					public void onProgressChanged(SeekBar seekBar,
							int progress, boolean fromUser) {
						// TODO Auto-generated method stub

					}
				});

		
		// Get initial data from intent (or default value):		
		Intent intent = getIntent();
		mStrSite = intent.getStringExtra("com.kernowsoft.specfx.SITENAME");
		if(mStrSite == null) mStrSite = "Croyde";
		mFcHr = intent.getIntExtra("com.kernowsoft.specfx.FCHR", 0);
		
		
		loadData();
	}

	private class DownloadJSONHelper extends AsyncTask<URL, Integer, String> {
		@Override
		protected String doInBackground(URL... url) {

			String strJson = new String();

			try {
				URLConnection con = url[0].openConnection();

				BufferedReader in = new BufferedReader(new InputStreamReader(
						con.getInputStream()));

				int count;
				int total = 0;
				int fileLength = con.getContentLength();
				mProgressDialog.setIndeterminate(fileLength < 0 ? true : false);
				// mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

				char[] buf = new char[256];

				while ((count = in.read(buf, 0, 255)) != -1) {
					total += count;
					strJson = strJson.concat(String.valueOf(buf, 0, count));
					publishProgress((int) (total * 100 / fileLength));
					// Log.i(TAG,
					// String.format("Loaded %d of %d", total, fileLength));
				}

				Log.i(TAG, "Done");
				in.close();

			} catch (MalformedURLException e) {
				Log.e(TAG, "Malformed URL: " + e.getMessage());
				e.printStackTrace();
			} catch (IOException e) {
				Log.e(TAG, "IO Exception: " + e.getMessage());
				e.printStackTrace();
			}

			return strJson;
		}

		// This member function runs in the UI thread, so is safe to update
		// any UI components
		protected void onPostExecute(String result) {
			if (result != null) {
				// update the ImageView with the downloaded bitmap:
				setSpecFromJSON(result);
			} else {
				((TextView) findViewById(R.id.siteName))
						.setText("Problem loading image...");
			}

			// mProgressDialog.dismiss();
			mProgressBar.setVisibility(View.INVISIBLE);
			
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mProgressBar.setProgress(0);
			// mProgressDialog.show();
			mProgressBar.setVisibility(View.VISIBLE);
		}

		@Override
		protected void onProgressUpdate(Integer... progress) {
			super.onProgressUpdate(progress);
			if (!mProgressBar.isIndeterminate())
				mProgressBar.setProgress(progress[0]);

			// if (!mProgressDialog.isIndeterminate())
			// mProgressDialog.setProgress(progress[0]);
		}
	}

	public void loadData() {

		if (mStrSite == null)
			return;

		// check cache:
		String strKey = String.format(Locale.UK, "%s_%03d", mStrSite, mFcHr);
		Log.i(TAG, "Checking data cache for key: " + strKey);
		if (mSpecDataCache.containsKey(strKey)) {
			Log.i(TAG, "Found data cached for: " + strKey);
			mSpecData = mSpecDataCache.get(strKey);

			updateViews();
			return;
		}

		// not in cache - download data:
		try {
			// String inputLine;
			String strUrl = String
					.format(Locale.UK,
							"http://www.ncof.co.uk/~ncof_webuser/spectral_wave/%s_%03d.json",
							mStrSite, mFcHr);
			Log.d(TAG, "URL is: " + strUrl);
			URL url = new URL(strUrl);
			new DownloadJSONHelper().execute(url);

		} catch (MalformedURLException e) {
			Log.e(TAG, "Malformed URL: " + e.getMessage());
		}
	}

	protected void setSpecFromJSON(String strJson) {

		// create new specData object:
		mSpecData = new SpecData();

		// decode the JSON string into the specData container:
		long t = System.currentTimeMillis();
		mSpecData.decodeJsonString(strJson);
		t = System.currentTimeMillis() - t;
		Log.d(TAG, "decodeJSONSring took: " + t + "ms");

		// update cache:
		String strKey = String.format(Locale.UK, "%s_%03d", mStrSite, mFcHr);
		Log.i(TAG, "Adding data to cache with key" + strKey);
		mSpecDataCache.put(strKey, mSpecData);

		// update views:
		updateViews();
	}

	private void updateViews() {

		// create the Spectral plot:
		mSpecDraw.setSpecData(mSpecData);

		// calc integrated parameters:
		float[] mn = mSpecData.integrate();
		float hsig = 4.0f * (float) Math.sqrt(mn[0]);
		float tm = mn[0] / mn[1];
		//float tz = (float) Math.sqrt(mn[0] / mn[2]);

		// Set meta data:
		((TextView) findViewById(R.id.siteName)).setText(mSpecData.sitename);

		((TextView) findViewById(R.id.siteInfo)).setText(String.format(
				"Wind: %3deg @ %dm/s", (int) mSpecData.windDir,
				(int) mSpecData.windSpeed));

		((TextView) findViewById(R.id.forecastTime)).setText(String.format(
				"%s (T+%03d)", new SimpleDateFormat("EEE dd/mm/yyyy HH:MM",
						Locale.UK).format(mSpecData.mDataTime), mFcHr));

		((TextView) findViewById(R.id.siteLocation)).setText(String.format(
				"%.2fN %.2fE", mSpecData.lat, mSpecData.lon));
		((TextView) findViewById(R.id.siteIntParms)).setText(String.format(
				"Hs: %.1fm, Tm %.1fs", hsig, tm));

	}

	/*
	 * public void loadDataAll() {
	 * 
	 * if (mStrSite == null) return;
	 * 
	 * mSpecDataList = new Vector<SpecData>(60);
	 * 
	 * String strJson = new String();
	 * 
	 * for (int i = 0; i < 60; i++) {
	 * 
	 * strJson = ""; try { String inputLine; String strUrl = String
	 * .format("http://www.ncof.co.uk/~ncof_webuser/spectral_wave/%s_%03d.json",
	 * mStrSite, i); Log.i(TAG, "URL is: " + strUrl); URL url = new URL(strUrl);
	 * 
	 * BufferedReader in = new BufferedReader(new InputStreamReader(
	 * url.openStream()));
	 * 
	 * while ((inputLine = in.readLine()) != null) //
	 * System.out.println(inputLine); strJson = strJson + inputLine;
	 * 
	 * in.close();
	 * 
	 * } catch (MalformedURLException e) { Log.e(TAG, "Malformed URL: " +
	 * e.getMessage()); } catch (IOException e) { Log.e(TAG, "IO Exception: " +
	 * e.getMessage()); e.printStackTrace(); }
	 * 
	 * // Log.i(TAG, "JSON: " + strJson); SpecData data = new SpecData();
	 * data.decodeJsonString(strJson); mSpecDataList.insertElementAt(data, i);
	 * 
	 * } }
	 */

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		// getMenuInflater().inflate(R.menu.activity_spec_draw, menu);
		// return true;

		super.onCreateOptionsMenu(menu);
		// menu.add(0, SELECT_SITE_ID, 0, R.string.menu_select_site);
		Menu sitemenu = menu.addSubMenu(0, SELECT_SITE_ID, 0,
				R.string.menu_select_site);

		sitemenu.add(0, 100, 0, "Croyde");
		sitemenu.add(0, 101, 0, "Perran");
		sitemenu.add(0, 102, 0, "Mountsbay");

		menu.add(0, HELP_ID, 1, R.string.menu_help);

		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		Log.d(TAG, "Item Id is " + item.getItemId());
		switch (item.getItemId()) {

		case 2:
			Toast.makeText(this, "SpecDraw, Copyright 2013 Chris Bunney",
					Toast.LENGTH_LONG).show();
			return true;

		case 100:
			mStrSite = "Croyde";
			loadData();
			return true;
		case 101:
			mStrSite = "Perran";
			loadData();
			return true;
		case 102:
			mStrSite = "Mountsbay";
			loadData();
			return true;
		}

		return super.onMenuItemSelected(featureId, item);
	}

}
